#ifndef	__STATE_INCLUDED__
#define	__STATE_INCLUDED__
#include"INC.h"
#pragma pack( push, 1 )

typedef	struct	tagFILEHDR {	
	BYTE	ID[12];		
	WORD	Reserved;
	WORD	BlockVersion;
} FILEHDR, *LPFILEHDR;


typedef	struct	tagFILEHDR2 {	
	BYTE	ID[12];		
	WORD	Reserved;
	WORD	BlockVersion;	

	DWORD	Ext0;		
	WORD	Ext1;		
	WORD	Ext2;		
	LONG	MovieStep;	
	LONG	MovieOffset;
} FILEHDR2, *LPFILEHDR2;

typedef	struct	tagBLOCKHDR {
	BYTE	ID[8];
	WORD	Reserved;
	WORD	BlockVersion;
	DWORD	BlockSize;
} BLOCKHDR, *LPBLOCKHDR;


typedef	struct	tagCPUSTAT_O {
	WORD	PC;
	BYTE	A;
	BYTE	X;
	BYTE	Y;
	BYTE	S;
	BYTE	P;
	BYTE	I;	
	BYTE	FrameIRQ;
	BYTE	reserved[3];

	LONG	mod_cycles;	

	
	SQWORD	emul_cycles;
	SQWORD	base_cycles;
} CPUSTAT_O, *LPCPUSTAT_O;


typedef	struct	tagCPUSTAT {
	WORD	PC;
	BYTE	A;
	BYTE	X;
	BYTE	Y;
	BYTE	S;
	BYTE	P;
	BYTE	I;	

	BYTE	FrameIRQ;
	BYTE	FrameIRQ_occur;
	BYTE	FrameIRQ_count;
	BYTE	FrameIRQ_type;
	LONG	FrameIRQ_cycles;

	LONG	DMA_cycles;

	SQWORD	emul_cycles;
	SQWORD	base_cycles;
} CPUSTAT, *LPCPUSTAT;


typedef	struct	tagPPUSTAT {
	BYTE * m_PatternTable;
	BYTE * m_NameTable[4];
	BYTE m_REG[0x04];						//$2000-$2003


	BYTE * s_current;
	BYTE s_x;
	BYTE s_y;


	BYTE * c_current;
	BYTE c_x;
	BYTE c_y;



	BYTE * current;
	BYTE LowAddr;
	BYTE HeightAddr;
	
	BYTE         m_Reg2007Temp;

	int          m_CurLineSprite;
	WORD         m_ByteIndex;
	WORD         m_CurByteIndex;
	BYTE         m_CurOffsetX8;
	BYTE         m_CurOffsetY8;
} PPUSTAT, *LPPPUSTAT;


typedef	struct	tagAPUSTAT_O {
	BYTE	reg[0x0018];
	BYTE	ext[0x0100];
} APUSTAT_O, *LPAPUSTAT_O;


typedef	struct	tagCTRREG {
	DWORD	pad1bit;
	DWORD	pad2bit;
	DWORD	pad3bit;
	DWORD	pad4bit;
	BYTE	strobe;
} CTRREG, *LPCTRREG;


typedef	struct	tagREGSTAT_O {
	union	uniCPUREG {
		BYTE	cpudata[32];
		CPUSTAT_O	cpu;
	} cpureg;
	union	uniPPUREG {
		BYTE	ppudata[32];
		PPUSTAT	ppu;
	} ppureg;
	APUSTAT_O	apu;
} REGSTAT_O, *LPREGSTAT_O;


typedef	struct	tagREGSTAT {
	union	uniCPUREG {
		BYTE	cpudata[64];
		CPUSTAT	cpu;
	} cpureg;
	union	uniPPUREG {
		BYTE	ppudata[32];
		PPUSTAT	ppu;
	} ppureg;
} REGSTAT, *LPREGSTAT;



typedef	struct	tagRAMSTAT {
	BYTE	RAM[2*1024];	// Internal NES RAM
	BYTE	BGPAL[16];	// BG Palette
	BYTE	SPPAL[16];	// SP Palette
	BYTE	SPRAM[256];	// Sprite RAM
} RAMSTAT, *LPRAMSTAT;


typedef	struct	tagMMUSTAT {
	LPBYTE	CPU_MEM_TYPE[8];
	WORD	CPU_MEM_PAGE[8];
	LPBYTE	PPU_MEM_TYPE[12];
	WORD	PPU_MEM_PAGE[12];
	BYTE	CRAM_USED[8];
} MMUSTAT, *LPMMUSTAT;


typedef	struct	tagMMCSTAT {
	BYTE	mmcdata[256];
} MMCSTAT, *LPMMCSTAT;


typedef	struct	tagCTRSTAT {
	union uniCTRDATA {
		BYTE	ctrdata[32];
		CTRREG	ctr;
	} ctrreg;
} CTRSTAT, *LPCTRSTAT;


typedef	struct	tagSNDSTAT {
	BYTE	snddata[0x800];	// 2KB
} SNDSTAT, *LPSNDSTAT;


typedef	struct	tagDISKSTAT {
	BYTE	DiskTouch[16];
} DISKSTAT, *LPDISKSTAT;


typedef	struct	tagDISKDATA {
	LONG	DifferentSize;
} DISKDATA, *LPDISKDATA;


typedef	struct	tagDISKIMGFILEHDR {	
	BYTE	ID[12];		
	WORD	BlockVersion;
	WORD	DiskNumber;
} DISKIMGFILEHDR, *LPDISKIMGFILEHDR;

typedef	struct	tagDISKIMGHDR {
	BYTE	ID[6];		
	BYTE	DiskTouch[16];
} DISKIMGHDR, *LPDISKIMGHDR;


typedef	struct	tagDISKFILEHDR {	
	BYTE	ID[12];		
	WORD	BlockVersion;	
	WORD	Reserved;
	DWORD	ProgID;		
	WORD	MakerID;	
	WORD	DiskNo;		
	DWORD	DifferentSize;	
} DISKFILEHDR, *LPDISKFILEHDR;


typedef	struct	tagEXCTRSTAT {
	DWORD	data;
} EXCTRSTAT, *LPEXCTRSTAT;


typedef	struct	tagMOVIEFILEHDR {
	BYTE	ID[12];			
	WORD	BlockVersion;		
	WORD	RecordVersion;		
	DWORD	Control;		
					
	DWORD	Ext0;			
	WORD	Ext1;			
	WORD	Ext2;			
	DWORD	RecordTimes;		

	BYTE	RenderMethod;		
	BYTE	IRQtype;		
	BYTE	FrameIRQ;		
	BYTE	VideoMode;		

	BYTE	reserved2[8];		

	LONG	StateStOffset;		
	LONG	StateEdOffset;		
	LONG	MovieOffset;		
	LONG	MovieStep;		

	DWORD	CRC;			
} MOVIEFILEHDR, *LPMOVIEFILEHDR;

typedef	struct	tagMOVIEIMGFILEHDRx {
	BYTE	ID[12];			
	WORD	BlockVersion;
	WORD	reserved;
	LONG	StateStOffset;		
	LONG	StateEdOffset;		
	LONG	MovieOffset;		
	LONG	MovieStep;		
} MOVIEIMGFILEHDRx, *LPMOVIEIMGFILEHDRx;


typedef	struct	tagFMVHDR {
	BYTE	ID[4];			
	BYTE	Control1;		
	BYTE	Control2;		
	DWORD	Unknown1;
	WORD	RecordTimes;		
	DWORD	Unknown2;
	BYTE	szEmulators[0x40];	
	BYTE	szTitle    [0x40];	
} FMVHDR, *LPFMVHDR;


typedef	struct	tagNMVHDR {
	BYTE	ExRAM[0x2000];
	BYTE	S_RAM[0x0800];
	WORD	PC;
	BYTE	A;
	BYTE	P;
	BYTE	X;
	BYTE	Y;
	BYTE	SP;
	BYTE	OAM[0x0100];
	BYTE	VRAM[0x4000];
	BYTE	Other[0xC9];
	DWORD	ScanlineCycles;
	DWORD	VblankScanlines;
	DWORD	FrameScanlines;
	DWORD	VirtualFPS;
} NMVHDR, *LPNMVHDR;


#define	SETBYTE(p,v)	{ *p = (v); p++; }
#define	SETWORD(p,v)	{ *(LPWORD)p = (v); p += sizeof(WORD); }
#define	SETDWORD(p,v)	{ *(LPDWORD)p = (v); p += sizeof(DWORD); }
#define	SETINT(p,v)	{ *(LPINT)p = (v); p += sizeof(INT); }
#define	SETBLOCK(p,v,s)	{ memcpy( p, (v), s ); p += s; }

#define	GETBYTE(p,v)	{ (v) = *p; p++; }
#define	GETWORD(p,v)	{ (v) = *(LPWORD)p; p += sizeof(WORD); }
#define	GETDWORD(p,v)	{ (v) = *(LPDWORD)p; p += sizeof(DWORD); }
#define	GETINT(p,v)	{ (v) = *(LPINT)p; p += sizeof(INT); }
#define	GETBLOCK(p,v,s)	{ memcpy( (v), p, s ); p += s; }

#pragma pack( pop )

#endif	// !__STATE_INCLUDED__
